package JavaUtils.net.socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

import JavaUtils.CSUtils.CBytes;
import JavaUtils.CSUtils.Log.CLog;
import JavaUtils.Action.Action1;

public class CTcpClient2T4L extends Thread {
    static final String tag = "C_TcpClient2T4L";

    /**
     * 开始监听Socket连接
     *
     * @param port
     * @param lngicCode
     * @throws IOException
     */
    public static void S_StartListener(int port, C2t4lLogic lngicCode) {
        C_Thread thread = new C_Thread();
        //thread.setDaemon(true);
        thread.port = port;
        thread.lngicCode = lngicCode;

        Thread tt = new Thread(thread);
        tt.setDaemon(true);
        tt.start();

    }

    static class C_Thread implements Runnable {
        public int port;
        public C2t4lLogic lngicCode;

        @Override
        public void run() {
            //super.run();
            try {
                ServerSocket server = new ServerSocket(port);
                CLog.f(tag, "  ---TCP 2T4L-IpV4服务器:post=={0}   已启动-------作者：夏海龙----", port);
                CLog.f(tag, "服务器准备就绪~");
                CLog.f(tag, "服务端信息：" + server.getInetAddress() + "port:" + server.getLocalPort());

                // 等待客户端连接
                for (; ; ) {
                    try {
                        // 得到客户端
                        Socket client = server.accept();
                        // 客户端构建异步线程
                        CTcpClient2T4L clientHandler = new CTcpClient2T4L(client, lngicCode);
                        // 启动线程
                        clientHandler.start();
                    } catch (IOException e) {
                        CLog.ex(tag, "错误推出....002");
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                CLog.ex(tag, "错误推出....001");
                e.printStackTrace();
            }
        }
    }

    ;

    static Thread threadV4, threadV6;

    public static void S_CloseListener() {
        if (threadV4 != null) {
            threadV4.stop();
        }
        if (threadV6 != null) {
            threadV6.stop();
        }
    }

    /**
     * 客户端消息处理
     */
    public Socket TcpClient() {
        return socket;
    }

    public String remoteAddressIp;//远程Ip
    public int remotePort;//远程端口
    byte[] megBytes = new byte[40960];
    public C2t4lLogic logicCode;

    Action1<C2t4lLogic> d_ConnectSuccessEvent;
    private Socket socket;
    private boolean flag = true;

    CTcpClient2T4L(Socket socket, C2t4lLogic lngicCode) {
        this.socket = socket;
        CLog.f(tag, "连接客户端地址：" + socket.getRemoteSocketAddress());
        this.logicCode = lngicCode.S_Clone(this);
    }

    @Override
    public void run() {
        super.run();
        CLog.f(tag, "新客户端连接：" + socket.getInetAddress() + "，port:" + socket.getPort());
        try {
            CLog.ex(tag, "监听消息.......................");
            DataInputStream inputStream = new DataInputStream(socket.getInputStream());
            byte[] megBytes = new byte[20480];
            int rlength;
            while (true) {
                //消息长度
                rlength = inputStream.read(megBytes);
                if (rlength > -1) {
                    CLog.f(tag, "接收的消息长度:" + rlength);
                    byte[] buffer1 = CBytes.subBytes(megBytes, 0, rlength);
                    S_CuttingBytes(buffer1, 0);
                }
            }
        } catch (Exception e) {
            CLog.f(tag, "连接异常断开");
        } finally {
            //连接关闭
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        CLog.f(tag, "客户端已退出：" + socket.getInetAddress() + "port:" + socket.getPort());
    }


    byte[] e_totalData;
    boolean e_isNewData = true;
    int o_数据累加长度;
    Short o_MsgType;
    byte moduleType, msgType;

    /// <summary>
    /// 切割二进制流
    /// </summary>
    void S_CuttingBytes(byte[] newBytes, int loopCount) {
        //CLog.LogFormat(" TCP新消息  消息长度={0}    粘包次数={1}", newBytes.Length, loopCount);
        if (e_isNewData) {
            if (newBytes.length < 6) {
                CLog.f(tag, " TCP新消息长度小于6____新消息长度==%d   %d", newBytes.length, loopCount);
            }
            try {
                moduleType = newBytes[0];
                msgType = newBytes[1];
                o_MsgType = (short) CBytes.S_256EncodeTo10Encode(CBytes.cut(newBytes, 0, 2));
                int langth = CBytes.S_256EncodeTo10Encode(CBytes.cut(newBytes, 2, 4));
                CLog.f(tag, ".消息长度...................%d......%d", langth, newBytes.length);
                e_totalData = new byte[langth];
            } catch (Exception ex) {
                e_isNewData = false;
                o_数据累加长度 = 0;
                try {
                    String ss = new String(newBytes, "utf-8").toString().trim();
                    //String ss = Encoding.UTF8.GetString(newBytes);
                    CLog.f(tag, " TCP接收到错误的消息____.%d......%d....%s", newBytes.length, ss);
                } catch (Exception ex2) {
                    CLog.f(tag, CLog.S_GetInfo(ex2, "消息处理出错"));
                }
                StringBuilder ssb = new StringBuilder();

                for (int i = 0; i < newBytes.length; i++) {
                    ssb.append("_");
                    ssb.append(newBytes[i]);
                }
                CLog.f(tag, "提示---(消息不满足T2L4协议)    %d.  %s  %s", newBytes.length, ssb.toString(), CLog.S_GetInfo(ex));
                return;
            }
            e_isNewData = false;
            o_数据累加长度 = 0;
            S_CuttingBytes(newBytes, 0);
        } else {
            if (o_数据累加长度 + newBytes.length >= e_totalData.length) {
                System.arraycopy(newBytes, 0, e_totalData, o_数据累加长度, e_totalData.length - o_数据累加长度);
                if (logicCode != null) {
                    try {
                        // CLog.LogFormat("<<==Tcp收到___" + o_消息类型 + "___" + msg);
                        logicCode.S_MessageHandle(moduleType, msgType, e_totalData);
                        logicCode.S_MessageHandle(o_MsgType, e_totalData);
                    } catch (Exception ex) {
                        CLog.ex(tag, "消息处理出错586", ex, false);
                    }
                }
                byte[] newData00 = new byte[newBytes.length - (e_totalData.length - o_数据累加长度)];
                e_isNewData = true;
                o_数据累加长度 = newData00.length;
                if (newData00.length != 0) {
                    System.arraycopy(newBytes, newBytes.length - newData00.length, newData00, 0, newData00.length);
                    loopCount++;
                    CLog.f(tag, "粘包了______________粘包次数=%d..____.累加长度=%d..___.总长度=%d.", loopCount, o_数据累加长度, e_totalData.length);
                    S_CuttingBytes(newData00, loopCount);
                }
            } else {
                System.arraycopy(newBytes, 0, e_totalData, o_数据累加长度, newBytes.length);
                o_数据累加长度 += newBytes.length;
            }
        }
    }


    public void S_SendMessage(short msgType, String msg) {
        CLog.f(tag, "==>>Tcp发送__" + msgType + "____" + remoteAddressIp + "____" + msg);
        byte[] bytes = msg.getBytes();
        S_SendMessage(msgType, bytes);
    }

    public void S_SendMessage(short msgType, byte[] data) {
        byte[] head = CBytes.S_10EncodeTo256Encode(((int) msgType), 2);
        int z消息长度 = 6 + data.length;
        byte[] z包长 = CBytes.S_10EncodeTo256Encode(z消息长度, 4);
        byte[] zData = CBytes.merge(CBytes.merge(head, z包长), data);
        S_SendMessage(zData);
    }

    public void S_SendMessage(byte moduleType, byte msgType, String msg) {
        // CLog.LogFormat("==>>Tcp发送__" + z消息类型 + "____"+o_IpPort.O_IP+"____"+ msg);
        byte[] data = msg.getBytes();//Encoding.UTF8.GetBytes(msg);
        S_SendMessage(moduleType, msgType, data);
    }

    public void S_SendMessage(byte moduleType, byte msgType, byte[] data) {
        byte[] dataType = new byte[]{moduleType, msgType};
        int z消息长度 = 6 + data.length;
        byte[] z包长 = CBytes.S_10EncodeTo256Encode(z消息长度, 4);
        byte[] zData = CBytes.merge(CBytes.merge(dataType, z包长), data);
        S_SendMessage(zData);
    }

    public void S_SendMessage(byte[] data) {
        if (socket.isConnected() == false) {
            //CLog.LogFormat("消息发送失败...tcp连接已经断开._____{0}_____{1}", remoteAddressIp,  sss.S_ToString(data,10));
            CLog.f(tag, "消息发送失败...tcp连接已经断开._____%s___", remoteAddressIp);
            return;
        }
        try {
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            dos.write(data, 0, data.length);
            dos.flush();
        } catch (Exception ex) {
            //S_FailInit(o_当前次数, "发送出错", ex);
        }
    }


    public void S_Close() throws IOException {
        CLog.f(tag, "ddddd========================================o_通信对象.Close();=============================");
        if (socket != null) {
            socket.close();
        }
        try {
            logicCode.S_Clese();
        } catch (Exception ex) {
            CLog.ef(tag, "关闭player逻辑错误__{0}", CLog.S_GetInfo(ex));
        }
    }
}

